/*
object.assign()方法用于对象的合并，将源对象（source）的所有可枚举属性，复制到目标对象（target）。
*/

const target = {
	a: 1
};

const source1 = {
	b: 2
};
const source2 = {
	c: 3
};

Object.assign(target, source1, source2); //Object.assign()方法的第一个参数是目标对象，后面的参数都是源对象。 
target // {a:1, b:2, c:3} 

/*
注意，如果目标对象与源对象有同名属性，或多个源对象有同名属性，则后面的属性会覆盖前面的属性。
*/
const target = {
	a: 1,
	b: 1
};

const source1 = {
	b: 2,
	c: 2
};
const source2 = {
	c: 3
};

Object.assign(target, source1, source2); //assign会返回合并后的对象，也会改变目标对象（target）
target // {a:1, b:2, c:3}


//由于undefined和null无法转成对象，所以如果它们作为目标对象，就会报错。
Object.assign(undefined) // 报错
Object.assign(null) // 报错


//如果undefined和null不在目标对象的位置， 就不会报错。
let obj = {
	a: 1
};
Object.assign(obj, undefined) === obj // true
Object.assign(obj, null) === obj // true



//其他类型的值（即数值、字符串和布尔值）不在首参数，也不会报错。但是，除了字符串会以数组形式，拷贝入目标对象，其他值都不会产生效果。
const v1 = 'abc';
const v2 = true;
const v3 = 10;
const obj = Object.assign({}, v1, v2, v3);
console.log(obj); // { "0": "a", "1": "b", "2": "c" } => 字符串类似数组，数组类似对象  链上有转换的方法，所以字符串能混进去
//通俗点说 => 字符串的包装对象，会产生可枚举属性。


/*
Object.assign()拷贝的属性是有限制的，只拷贝源对象的自身属性（不拷贝继承属性），也不拷贝不可枚举的属性（enumerable: false）。
*/
Object.assign({
		b: 'c'
	},
	Object.defineProperty({}, 'invisible', {
		enumerable: false,
		value: 'hello'
	})
)
// 返回的结果为{ b: 'c' }



//属性名为 Symbol 值的属性， 也会被Object.assign() 拷贝。
Object.assign({
	a: 'b'
}, {
	[Symbol('c')]: 'd'
})
// { a: 'b', Symbol(c): 'd' }


/*
要注意的地方

Object.assign()方法实行的是浅拷贝，而不是深拷贝。也就是说，如果源对象某个属性的值是对象，那么目标对象拷贝得到的是这个对象的引用。

对于这种嵌套的对象，一旦遇到同名属性，Object.assign()的处理方法是替换，而不是添加。

Object.assign()可以用来处理数组 比如 Object.assign([1, 2, 3], [4, 5]) => [4, 5, 3] 索引当属性

由于存在浅拷贝的问题，最好都是简单类型

*/


//Object.assign()只能进行值的复制，如果要复制的值是一个取值函数，那么将求值后再复制。
const source = {
	get foo() {
		return 1
	}
};
const target = {};
Object.assign(target, source) // { foo: 1 }


/*
常见用途
*/

//为对象添加属性
class Point {
	constructor(x, y) {
		Object.assign(this, {
			x,
			y
		});
	}
}


//为对象添加方法
Object.assign(SomeClass.prototype, {
	someMethod(arg1, arg2) {···}, //方法的简介表示
	anotherMethod() {···}
});


//克隆一个对象
function clone(origin) {
	return Object.assign({}, origin);
}



//合并多个对象 将多个对象合并到某个对象。
const merge =
	(target, ...sources) => Object.assign(target, ...sources);

//如果希望合并后返回一个新对象， 可以改写上面函数， 对一个空对象合并。
const merge =
	(...sources) => Object.assign({}, ...sources);




